#include <QMessageBox>
#include <QHostAddress>
#include "Preferences/preferences.h"
#include "constants.h"
#include "joinsession.h"
#include "ui_joinsession.h"

JoinSession::JoinSession(QWidget *parent) : QDialog(parent), ui(new Ui::JoinSession)
{
	ui->setupUi(this);

	//start browsing for services
	browser = new BonjourBrowser(this);
	connect(browser, SIGNAL(serviceListUpdated(QList<BonjourService>)),
			this, SLOT(updateServiceList(QList<BonjourService>)));
	connect(browser, SIGNAL(bonjourError()), this, SLOT(handleBonjourBrowserError()));
	browser->startBrowsing(QString(BONJOUR_PROTOCOL));

	//setup colour button
	pushButton_textColour = new ColourButton(this);
	ui->gridLayout_userInfo->addWidget(pushButton_textColour, 1, 2);

	//load the username and colour and port from preferences
	ui->lineEdit_user->setText(Preferences::getInstance()->getValue(Preferences::SETTING_DEFAULT_NAME).toString());
	pushButton_textColour->setColour(Preferences::getInstance()->getValue(Preferences::SETTING_DEFAULT_TEXT_COLOUR).value<QColor>());
	ui->spinBox_remotePort->setValue(DEFAULT_PORT);
}

JoinSession::~JoinSession()
{
	if (ui)
		delete ui;

	ui = NULL;
}

/**
  * Checks the settings, resolves the service into an ip (if needed)
  * and then completes the accept dialog action
  */
void JoinSession::accept()
{
	//check the user settings
	if (ui->lineEdit_user->text().isEmpty())
	{
		QMessageBox::warning(this, "Invalid User Information", "You must enter a valid name to join a session.");
		ui->lineEdit_user->setFocus();
		return;
	}

	// User has selected a bonjour session.
	if (ui->tabWidget->currentWidget() == ui->localTab)
	{
		// Check if bonjour record for WeaveEdit host is selected.
		if (ui->serviceListWidget->currentItem() == NULL)
		{
			QMessageBox::warning(this, "Invalid Session Information","No WeaveEdit session has been selected.");
			ui->serviceListWidget->setFocus();
			return;
		}

		//start the resolver
		BonjourService service = serviceList.at(ui->serviceListWidget->currentRow());	//get the wanted service
		resolver = new BonjourResolver(this);
		resolver->resolveService(service.index, service.name, QString(BONJOUR_PROTOCOL), service.domain);

		//connect a success and fail signals to slots, disable the ui, and wait....
		connect(resolver, SIGNAL(bonjourError()), this, SLOT(handleBonjourResolveError()));
		connect(resolver, SIGNAL(resolvedInfo(QString,quint16)), this, SLOT(getResolveInfoAndAccept(QString, quint16)));
		this->setEnabled(false);
	}

	//in the case of manually entered ip, accepting is straightforward
	if (ui->tabWidget->currentWidget() != ui->localTab)
	{
		// Check remote IP address for validity. Port is checked by UI spinbox range.
		if (!(QHostAddress().setAddress(ui->lineEdit_remoteIP->text())))
		{
			QMessageBox::warning(this, "Invalid Session Information","Host server IP is not valid.");
			ui->lineEdit_remoteIP->setFocus();
			return;
		}

		//save the username and text colour preferences
		Preferences::getInstance()->setValue(Preferences::SETTING_DEFAULT_NAME, ui->lineEdit_user->text());
		Preferences::getInstance()->setValue(Preferences::SETTING_DEFAULT_TEXT_COLOUR, pushButton_textColour->getColour());

		//save the connection data
		connectionData.first = ui->lineEdit_remoteIP->text();
		connectionData.second = ui->spinBox_remotePort->value();

		QDialog::accept();
	}
}

/**
  * This function is called when the bonjour resolve is complete and succesful
  * It saves all the data, then "accepts" the dialog
  */
void JoinSession::getResolveInfoAndAccept(QString host, quint16 port)
{
	//save the username and text colour preferences
	Preferences::getInstance()->setValue(Preferences::SETTING_DEFAULT_NAME, ui->lineEdit_user->text());
	Preferences::getInstance()->setValue(Preferences::SETTING_DEFAULT_TEXT_COLOUR, pushButton_textColour->getColour());

	//save the connection data
	connectionData.first = host;
	connectionData.second = port;

	delete resolver;
	resolver = NULL;

	QDialog::accept();
}

/**
  * Updates the service list with the list we receive from the bonjour browser
  */
void JoinSession::updateServiceList(QList<BonjourService> newList)
{
	serviceList = newList;	//save the new list

	//store the current row so we can maintain the users' selection
	int currentRow = ui->serviceListWidget->currentRow();

	if (currentRow < 0)
		currentRow = 0;

	ui->serviceListWidget->clear();

	//repopulate the ui
	foreach(BonjourService service, serviceList)
	{
		QListWidgetItem *item = new QListWidgetItem(ui->serviceListWidget);

		item->setText((service.name + " (" + service.domain + ")"));


	}

	ui->serviceListWidget->setCurrentRow(currentRow, QItemSelectionModel::Select);
}

/**
  * Tell the user to manually connect if bonjour returns errors
  */
void JoinSession::handleBonjourBrowserError()
{
	QMessageBox::warning(this, "Bonjour Error",
				 "Sorry, but Bonjour does not appear to be working.\nIt looks like you will have to connect manually.");

	//delete bonjour so it doesn't come back to haunt us
	delete browser;
	browser = NULL;

	ui->serviceListWidget->clear();
	ui->serviceListWidget->setEnabled(false);
}

/**
  * If the resolving failed, print an error message,
  * and return the user to the dialog as it was before
  * (as if nothing happened...)
  */
void JoinSession::handleBonjourResolveError()
{
	QMessageBox::warning(this, "Bonjour Error",
				 "The session you are trying to connect to could not be resolved.\nTry entering the connection infomation manually");

	delete resolver;
	resolver = NULL;

	this->setEnabled(true);
}

QString JoinSession::getUserName()
{
	return (ui->lineEdit_user->text());
}

QColor JoinSession::getUserColour()
{
	return (pushButton_textColour->getColour());
}

void JoinSession::changeEvent(QEvent *e)
{
	QDialog::changeEvent(e);

	switch (e->type())
	{
		case QEvent::LanguageChange:
			ui->retranslateUi(this);

			break;

		default:
			break;
	}
}
